// This is C# example on how to use Mongoose embeddable web server,
// http://code.google.com/p/mongoose
//
// Before using the mongoose module, make sure that Mongoose shared library is
// built and present in the current (or system library) directory

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Configuration;
using Microsoft.Office.Interop.Word;
using Org.Mentalis.Network;

namespace Tikarabbit
{

    public class TikarabbitServer
    {


        // Create a connection pool here.

        //static _Application[] oWord; 
        //static _Document[] oWordDoc;
        static Dictionary<String, Object> typeTable = new Dictionary<String, Object>();


        static TikarabbitServer()
        {


            typeTable["html"] = WdSaveFormat.wdFormatHTML;
            typeTable["txt"] = WdSaveFormat.wdFormatUnicodeText;
            typeTable["rtf"] = WdSaveFormat.wdFormatRTF;
            typeTable["xps"] = WdSaveFormat.wdFormatXPS;
            typeTable["pdf"] = WdSaveFormat.wdFormatPDF;


        }

        static Object missing = System.Reflection.Missing.Value;


        // This function is called when user types in his browser http://127.0.0.1:8080/

        static private void UriHandler(MongooseConnection conn, MongooseRequestInfo ri)
        {
            /*
            conn.write("HTTP/1.1 200 OK\r\n\r\n");
            conn.write("Hello from C#!\n");
            conn.write("Your user-agent is: " + conn.get_header("User-Agent") + "\n");
            conn.write("<br/> googe" + "\n");
        
            conn.write(my + "\n");
            WebRequest request = WebRequest.Create ("http://www1.yahoo.com");
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            conn.write(response.ContentType);
            */
            
            //conn.write(request.ContentType.ToString());

            String sUrl = conn.get_var("url");

            String type = conn.get_var("type");
            conn.write(sUrl + "<br/>");
            conn.write(type + "<br/>");
   
            try
            {
                Url url = new Url(sUrl);
                //String path = url.Host.Replace('.', '\\')+ '\\'+ url.Path;

                String newFileName = WEB_ROOT + "\\" + GetMd5Sum(sUrl) + "." + type;

                SaveAs(sUrl, ref newFileName, type);

                conn.write("new file:" + newFileName);

            }
            catch (Exception e)
            {
                conn.write("Unable to convert: " + e.Message + "<br/>");
            }
        }


        static String SaveAs(String fileName, ref string fileName2, String format)
    {
        
        object readOnly = true;
        // we can keep it false if you want to open the file but not make it invisible
        object isVisible = false;
        object openAndRepair = false;
        object noEncodingDialog = true;
        Object istrue = true;
        Object oFalse = false;
        Object oFalse2 = false;
        
        Object fileName1 = fileName;
        _Application oWord = OfficeObjectPool<Application>.Instance.GetObject();
        _Document oWordDoc = oWord.Documents.Open(
                ref fileName1,
                ref oFalse,
                ref readOnly, //yes
                ref missing,
                ref missing,
                ref missing,
                ref missing,
                ref missing,
                ref missing,
                ref missing,
                ref missing,
                ref isVisible, //false
                ref openAndRepair, //false
                ref missing,
                ref noEncodingDialog, //true
                ref missing);

        object format2 = typeTable[format];

        object fileName3 = fileName2; 

        oWordDoc.SaveAs(
                 ref fileName3,
                 ref format2,
                 ref  readOnly,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref isVisible,
                 ref missing,
                 ref missing,
                 ref missing,
                 ref missing
            );
        oWordDoc.Close(ref missing, ref missing, ref missing);
        OfficeObjectPool<Application>.Instance.Release((Application)oWord);
        return fileName2;
    }

        static String WEB_ROOT = "d:\\temp";
        static void Main()
        {

            //Console.WriteLine(typeof(Application));

            Mongoose web_server = new Mongoose();

            // Set options and /foo URI handler
            web_server.set_option("ports", "8080");
            web_server.set_option("root", WEB_ROOT);
            web_server.set_uri_callback("/conv", new MongooseCallback(UriHandler));

            // Serve requests until user presses "enter" on a keyboard
            Console.ReadLine();

            OfficeObjectPool<Application>.Instance.shutDownPool();
        }
       
        // Create an md5 sum string of this string
        static public string GetMd5Sum(string str)
        {
            // First we need to convert the string into bytes, which
            // means using a text encoder.
            Encoder enc = System.Text.Encoding.Unicode.GetEncoder();

            // Create a buffer large enough to hold the string
            byte[] unicodeText = new byte[str.Length * 2];
            enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);

            // Now that we have a byte array we can ask the CSP to hash it
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] result = md5.ComputeHash(unicodeText);

            // Build the final string by converting each byte
            // into hex and appending it to a StringBuilder
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < result.Length; i++)
            {
                sb.Append(result[i].ToString("X2"));
            }

            // And return it
            return sb.ToString();
        }

        public static string CalculateMD5Hash(string input)
        {
            // step 1, calculate MD5 hash from input
            MD5 md5 = MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hash = md5.ComputeHash(inputBytes);

            // step 2, convert byte array to hex string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            return sb.ToString();
        }

        public void finalizer()
        {
            //oWord.Quit(ref missing, ref missing, ref missing);


        }
    }


    public abstract class Singleton<T> where T : class
    {

        private static volatile T _instance;

        private static readonly object _locker = new object();



        public static T Instance
        {

            get
            {

                if (_instance == null)
                {

                    lock (_locker)
                    {

                        if (_instance == null)

                            _instance = Activator.CreateInstance(typeof(T), true) as T;

                    }

                }


                return _instance;

            }

        }

    }


}